﻿#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QDebug>
#include <QApplication>
#include <QStringList>
#include <QtEndian>
#include <QTime>
#include <QJsonDocument>
#include <QJsonObject>
#include <QFile>
#include <QJsonArray>
#include "QLineEdit"




MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::MainWindow)
{
    ui->setupUi(this);

    // 隐藏窗口标题栏
//    this->setWindowFlags(Qt::FramelessWindowHint);

    // 读取配置文件
#ifdef DEBUG
    QStringList tmp = QApplication::applicationDirPath().split("/");
    QString path = "";
    for (auto &item : qAsConst(tmp)) {
        path += item + QString("/");
    }
//    for(QStringList::iterator it = tmp.begin(); it != tmp.end() - 2; ++it){
//        path += *it + QString("/");
//    }
    path += QString("HMI") + CONFIG_PATH;

    getConfig(path);
#else
    getConfig(QApplication::applicationDirPath() + CONFIG_PATH);
#endif

    // 界面初始化
    initUI();

    // 网络初始化
    initNetwork();

    // 数据处理初始化
    initDataProcess();


//    connect(&mDisplayTimer, &QTimer::timeout, this, &MainWindow::updateUI);

//    mDisplayTimer.start(500);
}

MainWindow::~MainWindow()
{
    if (pStationDict) {
        delete pStationDict;
        pStationDict = NULL;
    }

    if (pDistScaleVector) {
        delete pDistScaleVector;
        pDistScaleVector = NULL;
    }

    delete ui;
}

// 设置数据处理间隔
void MainWindow::setDataProcessInterval(quint16 value)
{
    mDataProcessTimer.setInterval(value);
}

// 接收数据
void MainWindow::getReceivedData(QByteArray data)
{
    if (mMainNet == NETWORK::INIT) return;
    // 提取数据字段
    RECEIVED_MSG* pMsg = (RECEIVED_MSG*)data.mid(sizeof(RECEIVED_HEADER), sizeof (RECEIVED_MSG)).data();

    // 结构体转换大端
    toBigEndian(pMsg);

    // 将接收到的数据压入数据处理队列
    mReceivedMsgQueue.push_front(*pMsg);
}


// 数据处理
void MainWindow::processMsg()
{
    if (mReceivedMsgQueue.size() > 0) {

        // 取出队列最后一个数据
        RECEIVED_MSG* ptr = (RECEIVED_MSG*)&mReceivedMsgQueue.last();

        // 消息类型(byte_0)

        // 序列号(byte_1 to 4)

        // 预留1(byte_5 to 6)

        // 控车状态(byte_7)
        switch(pUdpSocket_J->getCab()) {
        case CAB::A:
        {
            switch (ptr->control_state) {
            case 0x00:                  // TC1不健康且不控车，TC2不健康且不控车
                ui->cabStatus->setLocalStatus(ACTIVE_STATUS::FAILURE);
                ui->cabStatus->setRemoteStatus(ACTIVE_STATUS::FAILURE);
                break;

            case 0x02:                  // TC1健康但不控车，TC2不健康且不控车
                ui->cabStatus->setLocalStatus(ACTIVE_STATUS::STANDBY);
                ui->cabStatus->setRemoteStatus(ACTIVE_STATUS::FAILURE);
                break;

            case 0x03:                  // TC1健康且控车，TC2不健康且不控车
                ui->cabStatus->setLocalStatus(ACTIVE_STATUS::ACTIVE);
                ui->cabStatus->setRemoteStatus(ACTIVE_STATUS::FAILURE);
                break;

            case 0x04:                  // TC1不健康且不控车，TC2健康但不控车
                ui->cabStatus->setLocalStatus(ACTIVE_STATUS::FAILURE);
                ui->cabStatus->setRemoteStatus(ACTIVE_STATUS::STANDBY);
                break;

            case 0x0C:                  // TC1不健康且不控车，TC2健康且控车
                ui->cabStatus->setLocalStatus(ACTIVE_STATUS::FAILURE);
                ui->cabStatus->setRemoteStatus(ACTIVE_STATUS::ACTIVE);
                break;

            case 0x0A:                  // TC1健康但不控车，TC2健康但不控车
                ui->cabStatus->setLocalStatus(ACTIVE_STATUS::STANDBY);
                ui->cabStatus->setRemoteStatus(ACTIVE_STATUS::STANDBY);
                break;

            case 0x0B:                  // TC1健康且控车，TC2健康但不控车
                ui->cabStatus->setLocalStatus(ACTIVE_STATUS::ACTIVE);
                ui->cabStatus->setRemoteStatus(ACTIVE_STATUS::STANDBY);
                break;

            case 0x0E:                  // TC1健康但不控车，TC2健康且控车
                ui->cabStatus->setLocalStatus(ACTIVE_STATUS::STANDBY);
                ui->cabStatus->setRemoteStatus(ACTIVE_STATUS::ACTIVE);
                break;

            default:
                break;
            }
            break;
        }

        case CAB::B:
        {
            switch (ptr->control_state) {
            case 0x00:                  // TC1不健康且不控车，TC2不健康且不控车
                ui->cabStatus->setLocalStatus(ACTIVE_STATUS::FAILURE);
                ui->cabStatus->setRemoteStatus(ACTIVE_STATUS::FAILURE);
                break;

            case 0x02:                  // TC1健康但不控车，TC2不健康且不控车
                ui->cabStatus->setLocalStatus(ACTIVE_STATUS::FAILURE);
                ui->cabStatus->setRemoteStatus(ACTIVE_STATUS::STANDBY);
                break;

            case 0x03:                  // TC1健康且控车，TC2不健康且不控车
                ui->cabStatus->setLocalStatus(ACTIVE_STATUS::FAILURE);
                ui->cabStatus->setRemoteStatus(ACTIVE_STATUS::ACTIVE);
                break;

            case 0x04:                  // TC1不健康且不控车，TC2健康但不控车
                ui->cabStatus->setLocalStatus(ACTIVE_STATUS::STANDBY);
                ui->cabStatus->setRemoteStatus(ACTIVE_STATUS::FAILURE);
                break;

            case 0x0C:                  // TC1不健康且不控车，TC2健康且控车
                ui->cabStatus->setLocalStatus(ACTIVE_STATUS::ACTIVE);
                ui->cabStatus->setRemoteStatus(ACTIVE_STATUS::FAILURE);
                break;

            case 0x0A:                  // TC1健康但不控车，TC2健康但不控车
                ui->cabStatus->setLocalStatus(ACTIVE_STATUS::STANDBY);
                ui->cabStatus->setRemoteStatus(ACTIVE_STATUS::STANDBY);
                break;

            case 0x0B:                  // TC1健康且控车，TC2健康但不控车
                ui->cabStatus->setLocalStatus(ACTIVE_STATUS::STANDBY);
                ui->cabStatus->setRemoteStatus(ACTIVE_STATUS::ACTIVE);
                break;

            case 0x0E:                  // TC1健康但不控车，TC2健康且控车
                ui->cabStatus->setLocalStatus(ACTIVE_STATUS::ACTIVE);
                ui->cabStatus->setRemoteStatus(ACTIVE_STATUS::STANDBY);
                break;

            default:
                break;
            }
            break;
        }

        default:
                break;

        }

        // 当前模式(byte_8)
        switch (ptr->cur_mode) {
        case 0x00:
            ui->curOpMode->setText("未知");
            break;

        case 0x01:
            ui->curOpMode->setText("RM");
            break;

        case 0x02:
            ui->curOpMode->setText("CM");
            break;

        case 0x03:
            ui->curOpMode->setText("AM");
             break;

        case 0x04:
            ui->curOpMode->setText("FAM");
            break;

        case 0x05:
            ui->curOpMode->setText("EUM");
            break;

        case 0x06:
            ui->curOpMode->setText("CAM");
            break;

        default:
            ui->curOpMode->setText("未知");
            break;
        }




        quint8 count = pPreSeleted->count();    // 预选模式数量
        QStringList modeList = {};
        // 最高可用模式(byte_9)
        modeList.append(QString(" RM"));        // RM模式始终显示在可用模式列表中
        switch (ptr->available_mode) {
        case 0x00:                  // 0b00000000
            ui->topMode->setText("RM");
            break;

        case 0x01:                  // 0b00000001
            ui->topMode->setText("CM");
            modeList.append(QString(" CM"));
            break;

        case 0x02:                  // 0b00000010
            ui->topMode->setText("AM");
            modeList.append(QString(" AM"));
            break;

        case 0x03:                  // 0b00000011
            ui->topMode->setText("AM");
            modeList.append(QString(" CM"));
            modeList.append(QString(" AM"));
            break;

        case 0x04:                  // 0b00000100
            ui->topMode->setText("FAM");
            modeList.append(QString(" CM"));
            modeList.append(QString(" FAM"));
            break;

        case 0x05:                  // 0b00000101
            ui->topMode->setText("FAM");
            modeList.append(QString(" FAM"));
            break;

        case 0x06:                  // 0b00000110
            ui->topMode->setText("FAM");
            modeList.append(QString(" AM"));
            modeList.append(QString(" FAM"));
            break;

        case 0x07:                  // 0b00000111
            ui->topMode->setText("FAM");
            modeList.append(QString(" CM"));
            modeList.append(QString(" AM"));
            modeList.append(QString(" FAM"));
            break;

        case 0x08:                  // 0b00001000
            ui->topMode->setText("CAM");
            modeList.append(QString(" CAM"));
            break;

        case 0x09:                  // 0b00001001
            ui->topMode->setText("CAM");
            modeList.append(QString(" CM"));
            modeList.append(QString(" CAM"));
            break;

        case 0x10:                  // 0b00001010
            ui->topMode->setText("CAM");
            modeList.append(QString(" AM"));
            modeList.append(QString(" CAM"));
            break;

        case 0x11:                  // 0b00001011
            ui->topMode->setText("CAM");
            modeList.append(QString(" CM"));
            modeList.append(QString(" AM"));
            modeList.append(QString(" CAM"));
            break;

        case 0x12:                  // 0b00001110
            ui->topMode->setText("CAM");
            modeList.append(QString(" AM"));
            modeList.append(QString(" FAM"));
            modeList.append(QString(" CAM"));
            break;

        case 0x13:                  // 0b00001111
            ui->topMode->setText("CAM");
            modeList.append(QString(" CM"));
            modeList.append(QString(" AM"));
            modeList.append(QString(" FAM"));
            modeList.append(QString(" CAM"));
            break;

        default:
            ui->topMode->setText("RM");
            break;

        }


        // 根据最新获取的当前可用模式列表设置预选模式下拉框
        if (count != modeList.count()) {
            QString text = pPreSeleted->currentText();
            pPreSeleted->clear();
            pPreSeleted->addItems(modeList);
            pPreSeleted->setCurrentText(text);
        }


        // 设置速度(byte_10 to 13)
        if (ptr->train_speed >= 0) {
            ui->dashBoard->setDigitalValue(ptr->train_speed);
        }

        if (0 > ptr->train_speed) {
            ui->align->setStatus(ALIGN_STATE::FALLBACK);
        }

        // 运行方向(byte_14)

        // 授权速度(byte_15 to 18)
        ui->dashBoard->setEmergencyValue(ptr->author_speed / 10);

        // FSB速度(byte_19 to 22)

        // 推荐速度(byte_23 to 26)
        ui->dashBoard->setAlarmValue(ptr->recommendation_speed / 10);

        // 目标距离(byte_27 to 30)
        ui->distInfo->setCurrentDistValue(ptr->target_distance / 1000);

        // 目标速度(byte_31 to 34)
        ui->distInfo->setTargetSpeed(ptr->target_speed / 10);

        // PSD状态(byte_35)
        switch(ptr->PSD_state) {
        case 0x02:
            ui->slipAndPSD->setState(STATE::PSD_NOT_CLOSED);
            break;

        default:
            ui->slipAndPSD->setState(STATE::INIT);
            break;
        }

        // 设置EB状态(byte_36)
        switch (ptr->EB_state) {
        case 0x00:
            pEb->setState(EB_STATE::INIT);
            break;

        case 0x01:
            pEb->setState(EB_STATE::EB);
            break;

        default:
            break;
        }

        // FSB状态(byte_37)

        // 列车位置标志(byte_38)
        switch (ptr->location_flag) {
        case 0x00:
            ui->transition->setState(TRANSITION_STATE::INIT);
            break;

        case 0x01:
//            break;

        case 0x02:
//            break;

        case 0x03:
            ui->transition->setState(TRANSITION_STATE::ENTER_DEPOT);
            break;

        default:
            break;

        }

        // TACS控车模式(byte_39)

        // 请求车控(byte_40)

        // 预留2(byte_41 to 42)

        // 预留3(byte_43 to 46)

        // 轮径校准状态(byte_47)

        // 对准信息(byte_48)
        switch (ptr->align) {
        case 0x00:
            ui->align->setStatus(ALIGN_STATE::INIT);
            break;

        case 0x01:
            ui->align->setStatus(ALIGN_STATE::ALIGN);
            break;

        default:
            break;
        }

        // 预选模式(byte_49)
        // 同步两端的预选模式
        switch (ptr->pre_selected_mode) {
        case 0x00:
            pPreSeleted->setCurrentText(" 未知");
            break;

        case 0x01:
            pPreSeleted->setCurrentText(" RM");
            break;

        case 0x02:
            pPreSeleted->setCurrentText(" CM");
            break;

        case 0x03:
            pPreSeleted->setCurrentText(" AM");
            break;

        case 0x04:
            pPreSeleted->setCurrentText(" FAM");
            break;

        default:
            pPreSeleted->setCurrentText(" FAM");
            break;
        }

        // 预留4(byte_50 to 53)

        // 上电检测(byte_54)

        // 车地通信状态(byte_55)

        // 预留5(byte_56 to 59)

        // 当前站(byte_60 to 63)

        // 下一站(byte_64 to 67)
        pNextStation->setStation(pStationDict->value(QString::number(ptr->next_station)).toString());

        // 终点站(byte_68 to 71)
        pDestination->setStation(pStationDict->value(QString::number(ptr->destination)).toString());

        // 停车距离(byte_72 to 75)

        // 下一站距离(byte_76 to 79)

        // 停站倒计时(byte_80 to 83)

        // 门控模式(byte_84)
        switch (ptr->door_mode) {
        case 0x00:
            ui->doorMode->setDoorState(DOORMODE::INIT);
            break;

        case 0x01:
            ui->doorMode->setDoorState(DOORMODE::AA);
            break;

        case 0x02:
            ui->doorMode->setDoorState(DOORMODE::AM);
            break;

        case 0x03:
            ui->doorMode->setDoorState(DOORMODE::MM);
            break;

        default:
            break;
        }

        // 发车提示(byte_85)
        switch(ptr->depature) {
        case 0x01:
            ui->departure->setState(DEPARTURESTATE::DEPARTURE);
            break;

        default:
            ui->departure->setState(DEPARTURESTATE::INIT);
            break;
        }

        // 折返状态(byte_86)
        switch (ptr->turn_back) {
        case 0x00:
            ui->turnback->setStatus(TURNBACK_STATUS::INIT);
            break;

        case 0x01:
            ui->turnback->setStatus(TURNBACK_STATUS::ACTIVATE);
            break;

        case 0x02:
            ui->turnback->setStatus(TURNBACK_STATUS::AVAILABLE);
            break;

        default:
            break;
        }

        // 设置牵引制动状态(byte_87)
        switch (ptr->motoring_state) {
        case 0x00:
            ui->motoringAndBrakingStatus->setStatus(TRACTION_STATUS::INIT);
            break;

        case 0x01:
            ui->motoringAndBrakingStatus->setStatus(TRACTION_STATUS::MOTORING);
            break;

        case 0x02:
            ui->motoringAndBrakingStatus->setStatus(TRACTION_STATUS::COASTING);
            break;

        case 0x03:
            ui->motoringAndBrakingStatus->setStatus(TRACTION_STATUS::BRAKING);
            break;

        default:
            break;
        }

        // 激活车头(byte_88)
        // 此处为激活车头处理代码

        // 例检A,B侧门状态(byte_89 to 90)
        switch (ptr->door_side_a_state << 1 | ptr->door_side_b_state) {
        case 0x01:      // 0b00000001
            ui->doorStatus->setDoorState(DOORSTATE::RIGHT_OPEN);
            break;

        case 0x02:      // 0b00000010
            ui->doorStatus->setDoorState(DOORSTATE::LEFT_OPEN);
            break;

        case 0x03:      // 0b00000011
            ui->doorStatus->setDoorState(DOORSTATE::BOTH_OPEN);
            break;

        case 0x05:      // 0b00000110
            ui->doorStatus->setDoorState(DOORSTATE::INIT);
            break;

        default:
            break;
        }

        // 上电例检提示(byte_91)


        // 获取报警时间
        QString datetime = QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm:ss") + "    ";

        // 报警原因(byte_92)
        switch (ptr->alarm_reason1 & 0b00001011) {
        case 0x01:
            pAlarmWindow->append(datetime + ALARM_NO_1);
            break;

        case 0x02:
            pAlarmWindow->append(datetime + ALARM_NO_2);
            break;

        case 0x03:
            pAlarmWindow->append(datetime + ALARM_NO_1);
            pAlarmWindow->append(datetime + ALARM_NO_2);
            break;

        case 0x08:
            pAlarmWindow->append(datetime + ALARM_NO_3);
            break;

        case 0x09:
            pAlarmWindow->append(datetime + ALARM_NO_1);
            pAlarmWindow->append(datetime + ALARM_NO_3);
            break;

        case 0x0A:
            pAlarmWindow->append(datetime + ALARM_NO_2);
            pAlarmWindow->append(datetime + ALARM_NO_3);
            break;

        case 0x0B:
            pAlarmWindow->append(datetime + ALARM_NO_1);
            pAlarmWindow->append(datetime + ALARM_NO_2);
            pAlarmWindow->append(datetime + ALARM_NO_3);
            break;

        default:
            break;
        }

        // 报警原因(byte_93)
        switch (ptr->alarm_reason2 & 0b00001000) {
        case 0x08:
            pAlarmWindow->append(datetime + ALARM_NO_4);
            break;

        default:
            break;
        }

        // 报警原因(byte_94)
        switch (ptr->alarm_reason3 & 0b01011000) {
        case 0x08:
            pAlarmWindow->append(datetime + ALARM_NO_5);
            break;

        case 0x10:
            pAlarmWindow->append(datetime + ALARM_NO_6);
            break;

        case 0x18:
            pAlarmWindow->append(datetime + ALARM_NO_5);
            pAlarmWindow->append(datetime + ALARM_NO_6);
            break;

        case 0x40:
            pAlarmWindow->append(datetime + ALARM_NO_7);
            break;

        case 0x48:
            pAlarmWindow->append(datetime + ALARM_NO_5);
            pAlarmWindow->append(datetime + ALARM_NO_7);
            break;

        case 0x50:
            pAlarmWindow->append(datetime + ALARM_NO_6);
            pAlarmWindow->append(datetime + ALARM_NO_7);
            break;

        case 0x58:
            pAlarmWindow->append(datetime + ALARM_NO_5);
            pAlarmWindow->append(datetime + ALARM_NO_6);
            pAlarmWindow->append(datetime + ALARM_NO_7);
            break;

        default:
            break;
        }

        // 报警原因(byte_95)

        // 报警原因(byte_96)
        for(quint8 n = 1; n < 8; n++) {
            switch(ptr->alarm_reason5 & (1 << n)) {
            case 0x02:
                pAlarmWindow->append(datetime + ALARM_NO_8);
                break;

            case 0x04:
                pAlarmWindow->append(datetime + ALARM_NO_9);
                break;

            case 0x08:
                pAlarmWindow->append(datetime + ALARM_NO_10);
                break;

            case 0x10:
                pAlarmWindow->append(datetime + ALARM_NO_11);
                break;

            case 0x20:
                pAlarmWindow->append(datetime + ALARM_NO_12);
                break;

            case 0x40:
                pAlarmWindow->append(datetime + ALARM_NO_13);
                break;

            case 0x80:
                pAlarmWindow->append(datetime + ALARM_NO_14);
                break;

            default:
                break;
            }
        }

        // 报警原因(byte_97)
        switch (ptr->alarm_reason6 & 0b10110000) {
        case 0x10:
            pAlarmWindow->append(datetime + ALARM_NO_15);
            break;

        case 0x20:
            pAlarmWindow->append(datetime + ALARM_NO_16);
            break;

        case 0x30:
            pAlarmWindow->append(datetime + ALARM_NO_15);
            pAlarmWindow->append(datetime + ALARM_NO_16);
            break;

        case 0x80:
            pAlarmWindow->append(datetime + ALARM_NO_17);
            break;

        case 0x90:
            pAlarmWindow->append(datetime + ALARM_NO_15);
            pAlarmWindow->append(datetime + ALARM_NO_17);
            break;

        case 0xA0:
            pAlarmWindow->append(datetime + ALARM_NO_16);
            pAlarmWindow->append(datetime + ALARM_NO_17);
            break;

        case 0xB0:
            pAlarmWindow->append(datetime + ALARM_NO_15);
            pAlarmWindow->append(datetime + ALARM_NO_16);
            pAlarmWindow->append(datetime + ALARM_NO_17);
            break;

        default:
            break;
        }

        // 报警原因(byte_98)
        for(quint8 n = 0; n < 5; n++) {
            switch(ptr->alarm_reason7 & (1 << n)) {
            case 0x01:
                pAlarmWindow->append(datetime + ALARM_NO_18);
                break;

            case 0x02:
                pAlarmWindow->append(datetime + ALARM_NO_19);
                break;

            case 0x04:
                pAlarmWindow->append(datetime + ALARM_NO_20);
                break;

            case 0x08:
                pAlarmWindow->append(datetime + ALARM_NO_21);
                break;

            case 0x10:
                pAlarmWindow->append(datetime + ALARM_NO_22);
                break;

            default:
                break;
            }
        }

        // 报警原因(byte_99)
        switch (ptr->alarm_reason8 & 0b10000000) {
        case 0x80:
            pAlarmWindow->append(datetime + ALARM_NO_23);
            break;

        default:
            break;
        }

        // 报警原因(byte_100)
        switch (ptr->alarm_reason9 & 0b01000010) {
        case 0x02:
            pAlarmWindow->append(datetime + ALARM_NO_24);
            break;

        case 0x40:
            pAlarmWindow->append(datetime + ALARM_NO_25);
            break;

        case 0x42:
            pAlarmWindow->append(datetime + ALARM_NO_24);
            pAlarmWindow->append(datetime + ALARM_NO_25);
            break;

        default:
            break;
        }

        // 报警原因(byte_101)
        switch (ptr->alarm_reason10 & 0b00000001) {
        case 0x01:
            pAlarmWindow->append(datetime + ALARM_NO_26);
            break;

        default:
            break;
        }

        // 报警原因(byte_102)
        switch (ptr->alarm_reason11 & 0b00000001) {
        case 0x01:
            pAlarmWindow->append(datetime + ALARM_NO_27);
            break;

        default:
            break;
        }

        // 报警原因(byte_103)
        for(quint8 n = 3; n < 7; n++) {
            switch(ptr->alarm_reason12 & (1 << n)) {
            case 0x08:
                pAlarmWindow->append(datetime + ALARM_NO_28);
                break;

            case 0x10:
                pAlarmWindow->append(datetime + ALARM_NO_29);
                break;

            case 0x20:
                pAlarmWindow->append(datetime + ALARM_NO_30);
                break;

            case 0x40:
                pAlarmWindow->append(datetime + ALARM_NO_31);
                break;

            default:
                break;
            }
        }

        // 报警原因(byte_104)

        // 报警原因(byte_105)
        for(quint8 n = 0; n < 4; n++) {
            switch(ptr->alarm_reason14 & (1 << n)) {
            case 0x01:
                pAlarmWindow->append(datetime + ALARM_NO_32);
                break;

            case 0x02:
                pAlarmWindow->append(datetime + ALARM_NO_33);
                break;

            case 0x04:
                pAlarmWindow->append(datetime + ALARM_NO_34);
                break;

            case 0x08:
                pAlarmWindow->append(datetime + ALARM_NO_35);
                break;

            default:
                break;
            }
        }

        // 报警原因(byte_106)

        // 报警原因(byte_107)

        // 报警原因(byte_108)
        switch (ptr->alarm_reason17 & 0b00000100) {
        case 0x04:
            pAlarmWindow->append(datetime + ALARM_NO_36);
            break;

        default:
            break;
        }

        // 报警原因(byte_109)
        switch (ptr->alarm_reason18 & 0b10000000) {
        case 0x80:
            pAlarmWindow->append(datetime + ALARM_NO_37);
            break;

        default:
            break;
        }

        // 报警原因(byte_110)
        for(quint8 n = 0; n < 8; n++) {
            switch(ptr->alarm_reason19 & (1 << n)) {
            case 0x01:
                pAlarmWindow->append(datetime + ALARM_NO_38);
                break;

            case 0x04:
                pAlarmWindow->append(datetime + ALARM_NO_39);
                break;

            case 0x40:
                pAlarmWindow->append(datetime + ALARM_NO_40);
                break;

            case 0x80:
                pAlarmWindow->append(datetime + ALARM_NO_41);
                break;

            default:
                break;
            }
        }

        // 报警原因(byte_111)
        for(quint8 n = 0; n < 4; n++) {
            switch(ptr->alarm_reason20 & (1 << n)) {
            case 0x01:
                pAlarmWindow->append(datetime + ALARM_NO_42);
                break;

            case 0x02:
                pAlarmWindow->append(datetime + ALARM_NO_43);
                break;

            case 0x04:
                pAlarmWindow->append(datetime + ALARM_NO_44);
                break;

            case 0x08:
                pAlarmWindow->append(datetime + ALARM_NO_45);
                break;

            default:
                break;
            }
        }

        // 报警原因(byte_112)

        // 报警原因(byte_113)

        // 报警原因(byte_114)

        // 报警原因(byte_115)

        // 报警原因(byte_116)
        switch (ptr->alarm_reason25 & 0b10100010) {
        case 0x02:
            pAlarmWindow->append(datetime + ALARM_NO_46);
            break;

        case 0x20:
            pAlarmWindow->append(datetime + ALARM_NO_47);
            break;

        case 0x22:
            pAlarmWindow->append(datetime + ALARM_NO_46);
            pAlarmWindow->append(datetime + ALARM_NO_47);
            break;

        case 0x80:
            pAlarmWindow->append(datetime + ALARM_NO_48);
            break;

        case 0x82:
            pAlarmWindow->append(datetime + ALARM_NO_46);
            pAlarmWindow->append(datetime + ALARM_NO_48);
            break;

        case 0xA0:
            pAlarmWindow->append(datetime + ALARM_NO_47);
            pAlarmWindow->append(datetime + ALARM_NO_48);
            break;

        case 0xA2:
            pAlarmWindow->append(datetime + ALARM_NO_46);
            pAlarmWindow->append(datetime + ALARM_NO_47);
            pAlarmWindow->append(datetime + ALARM_NO_48);
            break;

        default:
            break;
        }

        // 报警原因(byte_117)

        // 报警原因(byte_118)

        // 报警原因(byte_119)

        // 报警原因(byte_120)

        // 报警原因(byte_121)
        switch (ptr->alarm_reason30 & 0b10011000) {
        case 0x08:
            pAlarmWindow->append(datetime + ALARM_NO_49);
            break;

        case 0x10:
            pAlarmWindow->append(datetime + ALARM_NO_50);
            break;

        case 0x18:
            pAlarmWindow->append(datetime + ALARM_NO_49);
            pAlarmWindow->append(datetime + ALARM_NO_50);
            break;

        case 0x80:
            pAlarmWindow->append(datetime + ALARM_NO_51);
            break;

        case 0x88:
            pAlarmWindow->append(datetime + ALARM_NO_49);
            pAlarmWindow->append(datetime + ALARM_NO_51);
            break;

        case 0x90:
            pAlarmWindow->append(datetime + ALARM_NO_50);
            pAlarmWindow->append(datetime + ALARM_NO_51);
            break;

        case 0x98:
            pAlarmWindow->append(datetime + ALARM_NO_49);
            pAlarmWindow->append(datetime + ALARM_NO_50);
            pAlarmWindow->append(datetime + ALARM_NO_51);
            break;

        default:
            break;
        }

        // 报警原因(byte_122)
        switch (ptr->alarm_reason31 & 0b11000000) {
        case 0x40:
            pAlarmWindow->append(datetime + ALARM_NO_52);
            break;

        case 0x80:
            pAlarmWindow->append(datetime + ALARM_NO_53);
            break;

        case 0xC0:
            pAlarmWindow->append(datetime + ALARM_NO_52);
            pAlarmWindow->append(datetime + ALARM_NO_53);
            break;

        default:
            break;
        }

        // 报警原因(byte_123)
        switch (ptr->alarm_reason32 & 0b00000010) {
        case 0x02:
            pAlarmWindow->append(datetime + ALARM_NO_52);
            break;

        default:
            break;
        }
        // 报警窗口光标移到最后
//        pAlarmWindow->moveCursor(QTextCursor::End);
        pAlarmWindow->show();

        // 预留6(byte_132 to 133)

        // CRC8(byte_134)


        // 预留9~12(byte_135 to 147)


        // 从队列中清除已处理的数据
        mReceivedMsgQueue.removeLast();
    }

    // 显示时间
    ui->time->setText(QTime::currentTime().toString());

    // 主用网络选择
    selectMainNetwork();

}

void MainWindow::updateUI()
{
    if (pUdpSocket_J && pUdpSocket_R) {
        if (pUdpSocket_J->getConnectState() || pUdpSocket_R->getConnectState()){
            ui->widget1->show();
            ui->widget2->show();
            ui->widget3->show();
            ui->widget4->show();
            ui->widget5->show();
            ui->widget6->show();
            ui->widget7->show();
            ui->widget8->show();
            ui->widget9->show();
            ui->widget10->show();
            ui->widget11->show();
            ui->widget12->show();
            ui->widget13->show();
            ui->widget14->show();
            ui->widget15->show();
            ui->widget16->show();
            ui->widget17->show();
            ui->widget18->show();
            ui->widget19->show();
            ui->widget20->show();
            ui->widget21->show();
            ui->widget22->show();
            ui->widget23->show();
            ui->widget24->show();
            ui->widget25->show();
            pClockLabel->hide();
        }
        else {
            hideUI();
        }
    }
    else {
        hideUI();
    }

    this->update();
}


// 显示界面初始化
void MainWindow::initUI()
{
    pClockLabel = new QLabel(this);
    pClockLabel->setFixedSize(300, 50);
    pClockLabel->move(((this->width() - pClockLabel->width()) >> 1), ((this->height() - pClockLabel->height()) >> 1));
    pClockLabel->setAlignment(Qt::AlignCenter);

    QFont ft;
    ft.setPointSize(38);
    pClockLabel->setFont(ft);
    pClockLabel->hide();

//    pClockLabel->setStyleSheet("QLabel{font:38}");


    /* ----------------------------------------------界面设置--------------------------------------------------*/
    // 初始化界面
    pEb = new EbState(ui->widget1);
    pEb->setState(EB_STATE::INIT);

    pDestination = new Station(ui->widget8);
    pDestination->setTitle(QString("终点站:"));

    pNextStation = new Station(ui->widget9);
    pNextStation->setTitle(QString("下一站:"));

    // 临时功能
    pPreSeleted = new QComboBox(ui->widget12);
    pPreSeleted->addItem(QString(" RM"));

    connect(pPreSeleted, &QComboBox::textActivated, this, [&](){
        if (QString("RM") == pPreSeleted->currentText().split(" ").last()) {
            pUdpSocket_J->setPreMode(0x01);
            pUdpSocket_R->setPreMode(0x01);
        }
        if (QString("CM") == pPreSeleted->currentText().split(" ").last()) {
            pUdpSocket_J->setPreMode(0x02);
            pUdpSocket_R->setPreMode(0x02);
        }
        if (QString("AM") == pPreSeleted->currentText().split(" ").last()) {
            pUdpSocket_J->setPreMode(0x03);
            pUdpSocket_R->setPreMode(0x03);
        }
        if (QString("FAM") == pPreSeleted->currentText().split(" ").last()) {
            pUdpSocket_J->setPreMode(0x04);
            pUdpSocket_R->setPreMode(0x04);
        }
    });

    // 清空Label内容
    ui->trainnumber->clear();
    ui->curOpMode->clear();
    ui->topMode->clear();
    ui->systemMode->clear();

    // Label的文字居中设置
    ui->trainnumber->setAlignment(Qt::AlignCenter);
    ui->curOpMode->setAlignment(Qt::AlignCenter);
    ui->topMode->setAlignment(Qt::AlignCenter);
    ui->systemMode->setAlignment(Qt::AlignCenter);
    ui->time->setAlignment(Qt::AlignCenter);


    // 插件初始化状态设置
#ifdef QT_DEBUG
    ui->dashBoard->setDashboardStyle(DASHBOARD_STYLE::STANDARD);                // 仪表盘风格
    ui->motoringAndBrakingStatus->setStatus(TRACTION_STATUS::MOTORING);          // 牵引制动
    ui->integrity->setIntegrityStatus(INTEGRIGY::NORMAL);                       // 设置列车完整性初始化状态
    ui->cabStatus->setLocalStatus(ACTIVE_STATUS::ACTIVE);                       // 设置司机室激活初始化
    ui->holdAndSkip->setStatus(HOLD_SKIP_STATUS::SKIP);                         // 设置扣车和跳停初始化状态
    ui->turnback->setStatus(TURNBACK_STATUS::AVAILABLE);                         // 折返
    ui->align->setStatus(ALIGN_STATE::ALIGN);                                   // 停站对准
    ui->doorStatus->setDoorState(DOORSTATE::BOTH_OPEN);                         // 车门状态
    ui->departure->setState(DEPARTURESTATE::DEPARTURE);                         // 发车
    ui->doorMode->setDoorState(DOORMODE::AA);                                   // 门模式
    ui->slipAndPSD->setState(STATE::PSD_NOT_CLOSED);                            // 打滑和PSD
    ui->deviceFailureInfo->setState(DEVICE_FAILURE_INFO::ATO_FAILURE);          // 设备故障
    ui->transition->setState(TRANSITION_STATE::ENTER_DEPOT);                    // 转换轨
    ui->trainnumber->setText("T53214");                                           // 车次号
//    ui->trainnumber->setStyleSheet("QLabel{font:80}");
    ui->curOpMode->setText("FAM");                                              // 当前模式
    ui->topMode->setText("AM-C");                                                 // 最高预选模式
    ui->systemMode->setText("CTC");                                            // 系统模式
    pDestination->setStation(QString("龙阳路"));                               // 目的地
    pNextStation->setStation(QString("张江高科"));                              // 下一站
    pEb->setState(EB_STATE::ALARM);                                             // EB状态
    ui->distInfo->setCurrentDistValue(200);                                     // 目标距离
    ui->dashBoard->setEmergencyValue(20);
    ui->dashBoard->setAlarmValue(20);
    ui->distInfo->setTargetSpeed(50);
#endif

#ifdef QT_NO_DEBUG
    switch (mDashboardStyle) {
    case DASHBOARD_STYLE::STANDARD:
    default:
        ui->dashBoard->setDashboardStyle(DASHBOARD_STYLE::STANDARD);                // 标准速度表盘
        break;

    case DASHBOARD_STYLE::CUSTOMER:
        ui->dashBoard->setDashboardStyle(DASHBOARD_STYLE::CUSTOMER);                // 自定义速度表盘
        break;
    }
    ui->motoringAndBrakingStatus->setStatus(TRACTION_STATUS::INIT);             // 牵引制动
    ui->integrity->setIntegrityStatus(INTEGRIGY::LOST);                         // 设置列车完整性初始化状态
    ui->cabStatus->setLocalStatus(ACTIVE_STATUS::STANDBY);                      // 设置司机室激活初始化
    ui->holdAndSkip->setStatus(HOLD_SKIP_STATUS::NONE);                         // 设置扣车和跳停初始化状态
    ui->turnback->setStatus(TURNBACK_STATUS::INIT);                             // 折返
    ui->align->setStatus(ALIGN_STATE::INIT);                                    // 停站对准
    ui->doorStatus->setDoorState(DOORSTATE::INIT);                              // 车门状态
    ui->departure->setState(DEPARTURESTATE::INIT);                              // 发车
    ui->doorMode->setDoorState(DOORMODE::INIT);                                 // 门模式
    ui->slipAndPSD->setState(STATE::INIT);                                      // 打滑和PSD
    ui->deviceFailureInfo->setState(DEVICE_FAILURE_INFO::INIT);                 // 设备故障
    ui->transition->setState(TRANSITION_STATE::INIT);                           // 转换轨
#endif


    // 设置目标距离控件刻度
    if(pDistScaleVector) {
        ui->distInfo->setScaleVector(*pDistScaleVector);
    }

    // 已通过QSS进行配置logo，此处删除
//    QPixmap pixmap(":/images/logo.png");
//    ui->logo_label->setPixmap(pixmap);

//    ui->logo_label->setStyleSheet("QLabel#title_label{""background-image: url(:/images/logo.png);""}");

    QHBoxLayout* layout = new QHBoxLayout(ui->widget24);
    pAlarmWindow = new QTextBrowser;
    pAlarmWindow->setStyleSheet("color: white; font-size: 14px");
    layout->addWidget(pAlarmWindow);

}


// 网络初始化
void MainWindow::initNetwork()
{
#ifdef DEBUG
    QStringList tmp = QApplication::applicationDirPath().split("/");
    QString path = "";
//    for(QStringList::iterator it = tmp.begin(); it != tmp.end() - 2; ++it)
//    {
//        path += *it + QString("/");
//    }
    for (auto &item : qAsConst(tmp)) {
        path += item + QString("/");
    }
    path += QString("HMI") + COMMUNICATION_PATH;

    // 创建J网接口对象
    pUdpSocket_J = new UdpInterface(path);

    // 创建R网接口对象
    pUdpSocket_R = new UdpInterface(path);
#else
    // 创建J网接口对象
    pUdpSocket_J = new UdpInterface(QApplication::applicationDirPath() + COMMUNICATION_PATH);

    // 创建R网接口对象
    pUdpSocket_R = new UdpInterface(QApplication::applicationDirPath() + COMMUNICATION_PATH);
#endif

    // 设置窗口标题
    this->setWindowTitle(QString("CAB_") + QString::number(pUdpSocket_J->getCab()));

    // 绑定J网
    pUdpSocket_J->bindNet(NETWORK::J);

    // 从J网接口对象pUdpSocket_J接收数据
    connect(pUdpSocket_J, &UdpInterface::sendReceivedData, this, &MainWindow::getReceivedData);

    // 创建J网子线程
    pThread_J = new QThread(this);

    // 将J网接口对象pUdpSocket_J加入子线程pThread_J
    pUdpSocket_J->moveToThread(pThread_J);

    // 窗口关闭时结束子线程pThread_J
    connect(this, &MainWindow::destroyed, pThread_J, [&](){
        pThread_J->quit();
        pThread_J->wait();
    });

    // 启动J网子线程
    pThread_J->start();

    // 绑定R网
    pUdpSocket_R->bindNet(NETWORK::R);

    // 从R网接口对象pUdpSocket_R接收数据
    connect(pUdpSocket_R, &UdpInterface::sendReceivedData, this, &MainWindow::getReceivedData);

    // 创建R网子线程
    pThread_R = new QThread(this);

    // 将J网接口对象pUdpSocket_R加入子线程pThread_R
    pUdpSocket_R->moveToThread(pThread_R);

    // 窗口关闭时结束子线程pThread_R
    connect(this, &MainWindow::destroyed, pThread_R, [&](){
        pThread_R->quit();
        pThread_R->wait();
    });

    // 启动R网子线程
    pThread_R->start();

    // 主用网络选择
    selectMainNetwork();
}


// 数据处理初始化
void MainWindow::initDataProcess()
{
    // 初始化时清空数据处理队列
    mReceivedMsgQueue.clear();

    // 定期处理数据
    connect(&mDataProcessTimer, &QTimer::timeout, this, &MainWindow::processMsg);

    // 启动数据处理定时器
    mDataProcessTimer.start(DEFAULT_INTERVAL >> 1);
}



// 主用网络选择，根据网络连接状态选择主用网络
void MainWindow::selectMainNetwork()
{
    // 网络切换
    switch (mMainNet) {
    // 当前为J网时
    case NETWORK::J:
        // J网不健康，R网健康，切换至R网
        if(pUdpSocket_R->getConnectState() && !pUdpSocket_J->getConnectState()) {
            mMainNet = NETWORK::R;
            pUdpSocket_R->setMainNet(true);
            pUdpSocket_J->setMainNet(false);
            qDebug()<< "From J to R";
            break;
        }
        // J，R网均不健康，切换至初始化状态
        if(!pUdpSocket_J->getConnectState()) {
            mMainNet = NETWORK::INIT;
            pUdpSocket_R->setMainNet(false);
            pUdpSocket_J->setMainNet(false);
            qDebug()<< "From J to INIT";
            break;
        }
        break;

    // 当前为R网时
    case NETWORK::R:
        // R网不健康，J网健康，切换至J网
        if(pUdpSocket_J->getConnectState() && !pUdpSocket_R->getConnectState()) {
            mMainNet = NETWORK::J;
            pUdpSocket_J->setMainNet(true);
            pUdpSocket_R->setMainNet(false);
            qDebug()<< "From R to J";
            break;
        }
        // J，R网均不健康，切换至初始化状态
        if(!pUdpSocket_R->getConnectState()) {
            mMainNet = NETWORK::INIT;
            pUdpSocket_R->setMainNet(false);
            pUdpSocket_J->setMainNet(false);
            qDebug()<< "From R to INIT";
            break;
        }
        break;

    // 当前为初始状态
    case NETWORK::INIT:
        // J网健康选择J网
        if(pUdpSocket_J->getConnectState()) {
            mMainNet = NETWORK::J;
            pUdpSocket_J->setMainNet(true);
            pUdpSocket_R->setMainNet(false);
            qDebug()<< "From INIT to J";
            break;
        }
        // R网健康选择R网
        if(pUdpSocket_R->getConnectState()) {
            mMainNet = NETWORK::R;
            pUdpSocket_R->setMainNet(true);
            pUdpSocket_J->setMainNet(false);
            qDebug()<< "From INIT to R";
            break;
        }
        break;
    }
}


// 结构体数据从小端转大端
void MainWindow::toBigEndian(RECEIVED_MSG *pMsg)
{
    pMsg->msg_type = qToBigEndian(pMsg->msg_type);
    pMsg->sequence = qToBigEndian(pMsg->sequence);
    pMsg->reserved_1 = qToBigEndian(pMsg->reserved_1);
    pMsg->control_state = qToBigEndian(pMsg->control_state);
    pMsg->cur_mode = qToBigEndian(pMsg->cur_mode);
    pMsg->available_mode = qToBigEndian(pMsg->available_mode);
    pMsg->train_speed = qToBigEndian(pMsg->train_speed);
    pMsg->direction = qToBigEndian(pMsg->direction);
    pMsg->author_speed = qToBigEndian(pMsg->author_speed);
    pMsg->FSB_speed = qToBigEndian(pMsg->FSB_speed);
    pMsg->recommendation_speed = qToBigEndian(pMsg->recommendation_speed);
    pMsg->target_distance = qToBigEndian(pMsg->target_distance);
    pMsg->target_speed = qToBigEndian(pMsg->target_speed);
    pMsg->PSD_state = qToBigEndian(pMsg->PSD_state);
    pMsg->EB_state = qToBigEndian(pMsg->EB_state);
    pMsg->FSB_state = qToBigEndian(pMsg->FSB_state);
    pMsg->location_flag = qToBigEndian(pMsg->location_flag);
    pMsg->TACS_control_mode = qToBigEndian(pMsg->TACS_control_mode);
    pMsg->request_train_control = qToBigEndian(pMsg->request_train_control);
    pMsg->reserved_2 = qToBigEndian(pMsg->reserved_2);
    pMsg->reserved_3 = qToBigEndian(pMsg->reserved_3);
    pMsg->wheel_calibration = qToBigEndian(pMsg->wheel_calibration);
    pMsg->align = qToBigEndian(pMsg->align);
    pMsg->pre_selected_mode = qToBigEndian(pMsg->pre_selected_mode);
    pMsg->reserved_4 = qToBigEndian(pMsg->reserved_4);
    pMsg->routine_inspection_confirm = qToBigEndian(pMsg->routine_inspection_confirm);
    pMsg->communication_state = qToBigEndian(pMsg->communication_state);
    pMsg->reserved_5 = qToBigEndian(pMsg->reserved_5);
    pMsg->cur_station = qToBigEndian(pMsg->cur_station);
    pMsg->next_station = qToBigEndian(pMsg->next_station);
    pMsg->destination = qToBigEndian(pMsg->destination);
    pMsg->stop_dist = qToBigEndian(pMsg->stop_dist);
    pMsg->next_station_dist = qToBigEndian(pMsg->next_station_dist);
    pMsg->dwell_time = qToBigEndian(pMsg->dwell_time);
    pMsg->door_mode = qToBigEndian(pMsg->door_mode);
    pMsg->depature = qToBigEndian(pMsg->depature);
    pMsg->turn_back = qToBigEndian(pMsg->turn_back);
    pMsg->motoring_state = qToBigEndian(pMsg->motoring_state);
    pMsg->active_cab = qToBigEndian(pMsg->active_cab);
    pMsg->door_side_a_state = qToBigEndian(pMsg->door_side_a_state);
    pMsg->door_side_b_state = qToBigEndian(pMsg->door_side_b_state);
    pMsg->routine_inspection_prompt = qToBigEndian(pMsg->routine_inspection_prompt);
    pMsg->alarm_reason1 = qToBigEndian(pMsg->alarm_reason1);
    pMsg->alarm_reason2 = qToBigEndian(pMsg->alarm_reason2);
    pMsg->alarm_reason3 = qToBigEndian(pMsg->alarm_reason3);
//    pMsg->alarm_reason4 = qToBigEndian(pMsg->alarm_reason4);
    pMsg->alarm_reason5 = qToBigEndian(pMsg->alarm_reason5);
    pMsg->alarm_reason6 = qToBigEndian(pMsg->alarm_reason6);
    pMsg->alarm_reason7 = qToBigEndian(pMsg->alarm_reason7);
    pMsg->alarm_reason8 = qToBigEndian(pMsg->alarm_reason8);
    pMsg->alarm_reason9 = qToBigEndian(pMsg->alarm_reason9);
    pMsg->alarm_reason10 = qToBigEndian(pMsg->alarm_reason10);
    pMsg->alarm_reason11 = qToBigEndian(pMsg->alarm_reason11);
    pMsg->alarm_reason12 = qToBigEndian(pMsg->alarm_reason12);
//    pMsg->alarm_reason13 = qToBigEndian(pMsg->alarm_reason13);
    pMsg->alarm_reason14 = qToBigEndian(pMsg->alarm_reason14);
//    pMsg->alarm_reason15 = qToBigEndian(pMsg->alarm_reason15);
//    pMsg->alarm_reason16 = qToBigEndian(pMsg->alarm_reason16);
    pMsg->alarm_reason17 = qToBigEndian(pMsg->alarm_reason17);
    pMsg->alarm_reason18 = qToBigEndian(pMsg->alarm_reason18);
    pMsg->alarm_reason19 = qToBigEndian(pMsg->alarm_reason19);
    pMsg->alarm_reason20 = qToBigEndian(pMsg->alarm_reason20);
//    pMsg->alarm_reason21 = qToBigEndian(pMsg->alarm_reason21);
//    pMsg->alarm_reason22 = qToBigEndian(pMsg->alarm_reason22);
//    pMsg->alarm_reason23 = qToBigEndian(pMsg->alarm_reason23);
//    pMsg->alarm_reason24 = qToBigEndian(pMsg->alarm_reason24);
    pMsg->alarm_reason25 = qToBigEndian(pMsg->alarm_reason25);
//    pMsg->alarm_reason26 = qToBigEndian(pMsg->alarm_reason26);
//    pMsg->alarm_reason27 = qToBigEndian(pMsg->alarm_reason27);
//    pMsg->alarm_reason28 = qToBigEndian(pMsg->alarm_reason28);
//    pMsg->alarm_reason29 = qToBigEndian(pMsg->alarm_reason29);
    pMsg->alarm_reason30 = qToBigEndian(pMsg->alarm_reason30);
    pMsg->alarm_reason31 = qToBigEndian(pMsg->alarm_reason31);
    pMsg->alarm_reason32 = qToBigEndian(pMsg->alarm_reason32);
//    pMsg->reserved_6 = qToBigEndian(pMsg->reserved_6);
//    pMsg->reserved_7 = qToBigEndian(pMsg->reserved_7);
//    pMsg->reserved_8 = qToBigEndian(pMsg->reserved_8);
    pMsg->CRC = qToBigEndian(pMsg->CRC);
//    pMsg->reserved_9 = qToBigEndian(pMsg->reserved_9);
//    pMsg->reserved_10 = qToBigEndian(pMsg->reserved_10);
//    pMsg->reserved_11 = qToBigEndian(pMsg->reserved_11);
//    pMsg->reserved_12 = qToBigEndian(pMsg->reserved_12);

}


// 获取1个字节中指定位置的值，pos为0-7
quint8 MainWindow::getBitValue(quint8 value, quint8 pos)
{
    // pos校验
    if (7 < pos) return (-1);

    quint8 tValue1 = (value >> (pos + 1)) << (pos + 1);

    return (value ^ tValue1) >> pos;
}

void MainWindow::getConfig(QString path)
{
    QFile tConfig(path);

    if (!tConfig.open(QFile::ReadOnly)) {
        qDebug()<<"无法打开配置文件:" + path;
        return;
    }

    QByteArray tAllData = tConfig.readAll();
    tConfig.close();

    QJsonParseError tJsonError;
    QJsonDocument tJsonDoc(QJsonDocument::fromJson(tAllData, &tJsonError));

    if(tJsonError.error != QJsonParseError::NoError) {
        qDebug()<< "配置文件格式错误！";
        return;
    }

    QJsonObject tRootObj = tJsonDoc.object();

    // 获取Stations相关配置
    if (tRootObj.contains(QString("Stations"))) {
        pStationDict = new QJsonObject;
        *pStationDict = tRootObj.value("Stations").toObject();
    }

    // 获取DistScales相关配置
    if (tRootObj.contains(QString("DistScales"))) {
        pDistScaleVector = new QVector<quint16>;
        pDistScaleVector->clear();
        QJsonArray tArray = tRootObj.value("DistScales").toArray();
        for (auto item : qAsConst(tArray)) {
            pDistScaleVector->append(item.toInt());
        }
//        for (QJsonArray::iterator it = tArray.begin(); it != tArray.end(); ++it) {
//            pDistScaleVector->append(it->toInt());
//        }
    }

    // 获取表盘风格DashboardStyle相关配置
    if (tRootObj.contains(QString("DashboardStyle"))) {
        mDashboardStyle = tRootObj.value("DashboardStyle").toInt();
    }

}

void MainWindow::hideUI()
{
    ui->widget1->hide();
    ui->widget2->hide();
    ui->widget3->hide();
    ui->widget4->hide();
    ui->widget5->hide();
    ui->widget6->hide();
    ui->widget7->hide();
    ui->widget8->hide();
    ui->widget9->hide();
    ui->widget10->hide();
    ui->widget11->hide();
    ui->widget12->hide();
    ui->widget13->hide();
    ui->widget14->hide();
    ui->widget15->hide();
    ui->widget16->hide();
    ui->widget17->hide();
    ui->widget18->hide();
    ui->widget19->hide();
    ui->widget20->hide();
    ui->widget21->hide();
    ui->widget22->hide();
    ui->widget23->hide();
    ui->widget24->hide();
    ui->widget25->hide();

    pClockLabel->show();
    pClockLabel->setText(QTime::currentTime().toString("HH:mm:ss"));

}

